﻿using System;
using System.Windows.Forms;
using System.IO.Ports;

namespace TemperatureDisplay
{
    public partial class Temperatur : Form
    {
        SerialPort port;
        Message rx = new Message();
        Timer cyclic;
        int bytesToRead = 0;
        State status = 0;
        long messageCounter = 0;
        long sentMessageCounter = 0;
        byte second = 0;
        byte minute = 0;
        byte hour = 0;
        byte day = 0;
        byte month = 0;
        byte year = 0;

        byte sut_second = 0;
        byte sut_minute = 0;
        byte sut_hour = 0;
        byte sut_day = 0;
        byte sut_month = 0;
        byte sut_year = 0;

        enum State
        {
            sof1,
            sync,
            id,
            dlc,
            eof,
            unknown
        }

        public Temperatur()
        {
            InitializeComponent();
            rx = new Message();
            port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
            port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
            port.Open();
            cyclic = new Timer();
            cyclic.Interval = 250;
            cyclic.Start();
            cyclic.Tick += new EventHandler(cyclic_tick);
        }

        public void cyclic_tick(object sender, EventArgs eArgs)
        {
            tb_temp0.Text = ((double)(rx.getData(0)) / 2).ToString();
            tb_temp1.Text = ((double)(rx.getData(1)) / 2).ToString();
            tb_temp2.Text = ((double)(rx.getData(2)) / 2).ToString();
            tb_temp3.Text = ((double)(rx.getData(3)) / 2).ToString();
            tb_temp4.Text = ((double)(rx.getData(4)) / 2).ToString();
            tb_temp5.Text = ((double)(rx.getData(5)) / 2).ToString();
            tb_temp6.Text = ((double)(rx.getData(6)) / 2).ToString();
            tb_temp7.Text = ((double)(rx.getData(7)) / 2).ToString();
            tb_counter.Text = messageCounter.ToString();
            tb_counter_sent.Text = sentMessageCounter.ToString();
            tb_hour.Text = hour.ToString();
            tb_minute.Text = minute.ToString();
            tb_second.Text = second.ToString();
            tb_day.Text = day.ToString();
            tb_month.Text = month.ToString();
            tb_year.Text = year.ToString();
        }

        private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            while (port.BytesToRead != 0)
            {
                byte temp = (byte)port.ReadByte();
                switch (status)
                {
                    case State.unknown:
                        if (temp == 0xAA)
                            status = State.sof1;
                        break;
                    case State.sof1:
                        if (temp == 0x55)
                            status = State.sync;
                        else
                            status = State.unknown;
                        break;
                    case State.sync:
                        rx.id = temp;
                        status = State.id;
                        break;
                    case State.id:
                        rx.dlc = temp;
                        bytesToRead = rx.dlc;
                        if (bytesToRead == 0)
                            status = State.eof;
                        else
                            status = State.dlc;
                        break;
                    case State.dlc:
                        rx.setData(temp, rx.dlc - bytesToRead);
                        bytesToRead--;
                        if(bytesToRead == 0)
                            status = State.eof;
                        break;
                    case State.eof:
                        switch (rx.id)
                        {
                            case 0:
                                sendDate();
                                break;
                            case 1:
                                readDate();
                                break;
                            default:
                                break;
                        }
                        status = State.unknown;
                        break;
                    default:
                        status = State.unknown;
                        break;
                }
            }
        }

        private void sendDate()
        {
            DateTime now = DateTime.Now;
            Message msg = new Message();

            msg.id = 0;
            msg.dlc = 6;
            msg.setData((byte)(now.Year - 2000), 0);
            msg.setData((byte)now.Month, 1);
            msg.setData((byte)now.Day, 2);
            msg.setData((byte)now.Hour, 3);
            msg.setData((byte)now.Minute, 4);
            msg.setData((byte)now.Second, 5);

            sendMessage(msg);

            sentMessageCounter++;
        }

        private void readDate()
        {
            second = rx.getData(0);
            minute = rx.getData(1);
            hour = rx.getData(2);
            day = rx.getData(3);
            month = rx.getData(4);
            year = rx.getData(5);
        }

        private void sendMessage(Message msg)
        {
            byte[] tmp = new byte[12];

            tmp[0] = 0xAA;
            tmp[1] = 0x55;
            tmp[2] = msg.id;
            tmp[3] = msg.dlc;

            for (int i = 0; i < msg.dlc; i++)
            {
                tmp[i + 4] = msg.getData(i);
            }

            port.Write(tmp, 0, msg.dlc + 4);
        }

        private void tb_sut_TextChanged(object sender, EventArgs e)
        {
            sut_hour = string2byte(tb_sut_hour.Text);
            sut_minute = string2byte(tb_sut_minute.Text);
            sut_second = string2byte(tb_sut_second.Text);
            sut_year = string2byte(tb_sut_year.Text);
            sut_month = string2byte(tb_sut_month.Text);
            sut_day = string2byte(tb_sut_day.Text);
        }

        private byte string2byte(String str)
        {
            char[] temp = str.ToCharArray();
            byte ret = 0;

            if(temp.Length == 1)
                ret = (byte)(temp[0]-0x30);
            else if (temp.Length == 2)
            {
                ret = (byte)((temp[0]-0x30) * 10);
                ret += (byte)(temp[1]-0x30);
            }

            return ret;
        }

        private void btn_send_Click(object sender, EventArgs e)
        {
            Message msg = new Message();

            msg.id = 4;
            msg.dlc = 6;

            msg.setData(sut_year, 0);
            msg.setData(sut_month, 1);
            msg.setData(sut_day, 2);
            msg.setData(sut_hour, 3);
            msg.setData(sut_minute, 4);
            msg.setData(sut_second, 5);

            sendMessage(msg);
        }
    }

    public class Message
    {
        private byte _id;
        private byte _dlc;

        public byte id
        {
            set { this._id = value; }
            get { return this._id; }
        }
        public byte dlc
        {
            set { this._dlc = value; }
            get { return this._dlc; }
        }
        byte[] data = new byte[8];

        public Message()
        {
            id = 0;
            dlc = 0;
            foreach (byte i in data)
            {
                data[i] = 0;
            }
        }

        public byte getData(int index)
        {
            return data[index];
        }

        public void setData(byte data_in, int index)
        {
            data[index] = data_in;
        }
    }
}
